from tortoise.expressions import Q, F
from tortoise.transactions import in_transaction

from app.controllers.marketing.integral import integral_controller
from app.controllers.orders.list import orders_list_controller
from app.controllers.saas.buckling import buckling_controller
from app.controllers.saas.buckling_detail import buckling_detail_controller
from app.controllers.saas.consumables_use import consumables_use_controller
from app.controllers.saas.performance_percentage import performance_percentage_controller
from app.core.crud import CRUDBase
from app.models import BucklingDetail, OrdersList, OrdersGoods, Goods, BucklingGroup, GoodsGroup, CustomerUser
from app.models.saas import Cases, Buckling, BucklingTodo
from app.schemas.marketing import IntegralCreate
from app.schemas.saas import CasesCreate, CasesUpdate, BucklingDetailCreate, ConsumablesCreate, BaseConsumablesUse, \
    PerformancePercentageCreate
from app.log.log import logger


class TransactionError(Exception):
    """自定义异常类，用于事务失败时回滚"""
    pass


class CasesController(CRUDBase[Cases, CasesCreate, CasesUpdate]):
    def __init__(self):
        super().__init__(model=Cases)

    async def do_list(self, page: int, page_size: int, search: Q = Q()):
        query = self.model.filter(search)
        total = await query.count()
        objs = await query.offset((page - 1) * page_size).limit(page_size).order_by('-id')
        data = [await obj.to_dict(exclude_fields=["updated_at", "deleted_at"]) for obj in objs]
        return total, data

    async def do_detail(self, data_id: int):
        obj = await self.get(id=data_id)
        data = await obj.to_dict()
        return data

    async def do_create(self, obj_in: CasesCreate):
        try:
            async with in_transaction() as transaction:
                ret = await self.create(obj_in=obj_in)
                buckling_data = obj_in.buckling_data
                for item in buckling_data:
                    ##批量插入划扣记录
                    buckling_id = item["buckling_id"]
                    group_id = 0
                    if item.get("group_id") is not None:
                        group_id = item["group_id"]
                    nums = item["nums"]
                    buckling = await Buckling.get(id=buckling_id)
                    buckling_dict = await buckling.to_dict()
                    if nums > 0:
                        date_detail = BucklingDetailCreate(
                            buckling_id=buckling_id,
                            nums=nums,
                            space_id=obj_in.space_id,
                            cases_id=ret.id,
                            buckling_price=buckling_dict['price'] / nums
                        )
                        await buckling_detail_controller.do_create(obj_in=date_detail)
                    logger.info(f"批量插入划扣记录完成: {buckling_id}")
                    ##更新buckling的使用记录和剩余数量
                    buckling_data = await Buckling.filter(id=buckling_id).first().values("use_nums", "last_nums",
                                                                                         "todo_id")
                    use_nums = buckling_data["use_nums"]
                    last_nums = buckling_data["last_nums"]
                    new_use_nums = use_nums + nums
                    new_last_nums = last_nums - nums
                    if new_last_nums < 0:
                        # 手动抛出异常来触发回滚
                        logger.info(f"不足划扣请检查,划扣编号: {buckling_id}")
                        raise TransactionError(f"不足划扣请检查,划扣编号: {buckling_id}")
                    logger.info(f"更新buckling的使用记录和剩余数量完成: {buckling_id}")
                    buckling = await Buckling.filter(id=item['id']).first().values()
                    good = await Goods.filter(id=buckling['goods_id']).first().values()
                    if good['rebate'] == 2:
                        if good['get_integral']:
                            logger.info(f"获得积分")
                            # 获得积分
                            buckling_todo = await BucklingTodo.filter(id=buckling['todo_id']).first().values()
                            if buckling_todo['type'] == 1:
                                integral_data = IntegralCreate(
                                    user_id=buckling["user_id"],
                                    price=int((good['get_integral'] / buckling_nums) * nums),
                                    direction=1,
                                    type=1,
                                    type_id=buckling['order_id'],
                                    remark="划扣获得积分",
                                    space_id=buckling['space_id']
                                )
                                await integral_controller.do_create(obj_in=integral_data)
                            if buckling_todo['type'] == 2:
                                buckling_group = await BucklingGroup.filter(
                                    todo_id=buckling_todo['id']).first().values()
                                print(buckling_group)
                                if buckling_group['group_type'] == 1:
                                    good_group = await GoodsGroup.filter(
                                        id=buckling_group['group_id']).first().values()
                                    buckling_nums = 0
                                    for buckling_good in good_group['goods']:
                                        buckling_nums += buckling_good['num']
                                if buckling_group['group_type'] == 2:
                                    buckling_nums = buckling_group['times']
                                integral_data = IntegralCreate(
                                    user_id=buckling["user_id"],
                                    price=int((good['get_integral'] / buckling_nums) * nums),
                                    direction=1,
                                    type=1,
                                    type_id=buckling['order_id'],
                                    remark="划扣获得积分",
                                    space_id=buckling['space_id']
                                )
                                await integral_controller.do_create(obj_in=integral_data)
                                await CustomerUser.filter(id=buckling["user_id"]).update(
                                    money_integral=F('money_integral') + int((good['get_integral'] / buckling_nums) * nums),
                                )

                    ##开卡触发权益
                    # await orders_list_controller.do_give(buckling['order_id'])
                    ##更新各种状态
                    await Buckling.filter(id=buckling_id).update(use_nums=new_use_nums, last_nums=new_last_nums)
                    if group_id:
                        await BucklingGroup.filter(id=group_id).update(use_times=new_use_nums, last_times=new_last_nums)
                    logger.info(f"更新group_id完成: {buckling_id}")
                    last_nums_arr = await Buckling.filter(todo_id=buckling_data["todo_id"]).values_list('last_nums',
                                                                                                        flat=True)
                    has_positive = any(last_nums > 0 for last_nums in last_nums_arr)
                    if has_positive is False:
                        await BucklingTodo.filter(id=buckling_data["todo_id"]).update(status=2)
                    # 业绩
                    # performance_detail = PerformancePercentageCreate(
                    #     order_id=0,
                    #     goods_id=item.sku_id,
                    #     sku_id=item.sku_id,
                    #     customer_id=obj_in.user_id,
                    #     user_id=0,
                    #     space_id=obj_in.space_id,
                    #     price=0,
                    #     buckling_id=item.buckling_id,
                    #     status=0,
                    # )
                    # await performance_percentage_controller.do_create(obj_in=performance_detail)
                # 耗材
                buckling_consumables = obj_in.buckling_consumables
                if buckling_consumables:
                    for consumable in buckling_consumables:
                        ##批量插入划扣记录
                        case_id = ret.id
                        nums = consumable["nums"]
                        if nums > 0:
                            date_detail = BaseConsumablesUse(
                                consumables_id=consumable["id"],
                                nums=nums,
                                cases_id=case_id,
                                user_id=obj_in.user_id,
                                space_id=obj_in.space_id
                            )
                            await consumables_use_controller.do_create(obj_in=date_detail)
                logger.info(f"更新耗材完成")

            return True
        except TransactionError:
            # 捕获自定义异常并返回 False
            return False  # 事务回滚后返回 False

        except Exception as e:
            # 其他异常捕获，确保所有错误都会返回 False
            return False

    async def do_update(self, obj_in: CasesUpdate):
        await self.update(id=obj_in.id, obj_in=obj_in)
        return True

    async def do_delete(self, data_id: int):
        async with in_transaction() as transaction:
            await self.remove(id=data_id)
            details = await BucklingDetail.filter(cases_id=data_id).all().values()
            for item in details:
                ##每一条都给他恢复
                buckling_data = await Buckling.filter(id=item["buckling_id"]).first().values("use_nums", "last_nums")
                use_nums = buckling_data["use_nums"]
                last_nums = buckling_data["last_nums"]
                new_use_nums = use_nums - item["nums"]
                new_last_nums = last_nums + item["nums"]
                await Buckling.filter(id=item["buckling_id"]).update(use_nums=new_use_nums, last_nums=new_last_nums)
                await buckling_detail_controller.do_delete(data_id=item["id"])
        return True


cases_controller = CasesController()
